import { Spin, Menu, type MenuProps } from 'antd';
import React, { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import type { RootState } from '../../../store'
import { findAllBreadcrumb, getOpenKeys, searchRoute } from '../../../utils/utils'
import { getMenuList } from '../../../apis/modules/login'
import * as Icons from '@ant-design/icons'
import { setMenuList } from '../../../store/modules/menu'
import Logo from './components/Logo'
import './style/index.scss'
import { setBreadcrumbList } from '../../../store/modules/breadcrumb'

const LayoutMenu = () => {
  // 定义 menu 类型
  type MenuItem = Required<MenuProps>["items"][number];
  
  const { pathname } = useLocation();
  const [ loading, setLoading ] = useState(true)
  const [ menuListData, setMenuListData ] = useState<MenuItem[]>([])
  const [ openKeys, setOpenKeys ] = useState<string[]>([])
  const [ selectedKeys, setSelectedKeys ] = useState<string[]>([pathname])
  const { isCollapse, menuList } = useSelector((state: RootState) => state.menu)

  const dispatch = useDispatch()
   // 刷新页面菜单保持高亮
   useEffect(() => {
    setSelectedKeys([pathname]);
    if (!isCollapse) {
      setOpenKeys(getOpenKeys(pathname))
    }
    }, [pathname, isCollapse])

    // 设置当前展开的 subMenu
    const onOpenChange = (openKeys: string[]) => {
      if (openKeys.length <= 1) return setOpenKeys(openKeys)
      const latestOpenKey = openKeys[openKeys.length - 1]
      if (latestOpenKey.includes(openKeys[0])) return setOpenKeys(openKeys)
      setOpenKeys([latestOpenKey])
    }
    
    // 动态渲染 Icon 图标
    const customIcons: {[key: string]: any} = Icons;
    const addIcon = (name: string): React.ReactElement => {
      return name ? React.createElement(customIcons[name]) : <></>
    }

    const getItem = (label: React.ReactNode, key: React.Key | null, icon?: React.ReactNode, children?: MenuItem[], type?: 'group'): MenuItem => {
      return {
        key,
        icon,
        children,
        label,
        type
      } as MenuItem
    }

    // 处理后台返回菜单 key 值为 antd 菜单需要的 key 值
    const deepLoopFloat = (menuList: MenuItem.MenuOptions[], newArr: MenuItem[] = []) => {
      menuList.forEach((item: Menu.MenuOptions) => {
        if (!item?.children?.length) return newArr.push(getItem(item.title, item.path, addIcon(item.icon as string)))
        newArr.push(getItem(item.title, item.path, addIcon(item.icon as string), deepLoopFloat(item.children)))
      })
      return newArr
    }

    // 获取菜单列表并处理成 antd menu 需要的格式
    const getMenuData = async () => {
      setLoading(true)
      try {
        const { data } = await getMenuList()
        if (!data) return
        setMenuListData(deepLoopFloat(data))
        dispatch(setMenuList(data))
        // 存储处理过后的所有面包屑导航栏到 redux 
        dispatch(setBreadcrumbList(findAllBreadcrumb(data)))
      } finally {
        setLoading(false)
      }
    }

    useEffect(() => {
      getMenuData()
    }, [])

    const navigate = useNavigate()
    const clickMenu: MenuProps["onClick"] = ({ key }: { key: string }) => {
      const route = searchRoute(key, menuList)
      if (route.isLink) window.open(route.isLink, "_blank")
      navigate(key)
    }

    return (
      <div className="menu">
        <Spin spinning={loading}>
          <Logo />
          <Menu
            mode="inline"
            theme="dark"
            triggerSubMenuAction="click"
            onClick={clickMenu}
            items={menuListData}
            openKeys={openKeys}
            selectedKeys={selectedKeys}
            onOpenChange={onOpenChange}
          />
        </Spin>
      </div>
    )
}

export default LayoutMenu;
